package com.bourse.core.utils;

import java.util.ArrayList;
import java.util.Date;

import org.joda.time.DateMidnight;

import com.bourse.core.exceptions.TimeSerieException;

public class TimeSerieObject<T> {

	private ArrayList<DateMidnight> dates = new ArrayList<DateMidnight>();
	private ArrayList<T> datas = new ArrayList<T>();

	/**
	 * Return the first date
	 * @return
	 */
	public DateMidnight getFirstDate() {
		return dates.get(0);
	}

	/**
	 * Return the last date
	 * @return
	 */
	public DateMidnight getLastDate() {
		return dates.get(dates.size() - 1);
	}

	/**
	 * Return the first date before the current
	 * @param theDate
	 * @return
	 */
	public DateMidnight getLastDateBefore(DateMidnight theDate){
		DateMidnight returnedDate = null;
		for(DateMidnight date : dates){
			if(date.isBefore(theDate)){			
				returnedDate = date;
			}else{
				break;
			}
			
		}
		return returnedDate;
	}
	
	/**
	 * Return the first date after the one given in parameter
	 * @param theDate
	 * @return
	 */
	public DateMidnight getFirstDateAfter(DateMidnight theDate){
		DateMidnight returnedDate = null;
		for(DateMidnight date : dates){
			if(date.isAfter(theDate)){			
				returnedDate = date;
			}
		}
		return returnedDate;
	}
	
	/** 
	 * Return true if the date exists in the time serie
	 * @param dt
	 * @return
	 */
	public boolean exist(Date dt) {
		return dates.contains(dt);
	}

	/** 
	 * return the timeserie size
	 * @return
	 */
	public int size() {
		return dates.size();
	}

	/**
	 * Adding data to the time serie
	 * 
	 * @param dt
	 * @param value
	 * @throws TimeSerieException
	 */
	public void add(DateMidnight dt, T value) throws TimeSerieException {

		if (dates.size() != 0) {
			for (int i = 0; i < dates.size(); i++) {
				if (dt.isBefore(dates.get(i))) {
					throw new TimeSerieException("Back date exception");
				}
			}
			dates.add(dt);
			datas.add(value);
		} else {
			dates.add(dt);
			datas.add(value);
		}
	}

	/** 
	 * Returned the timeserie specified between the two dates
	 * @param bDate
	 * @param eDate
	 * @return
	 * @throws TimeSerieException
	 */
	public TimeSerieObject<T> getTimeSerie(DateMidnight bDate, DateMidnight eDate)
			throws TimeSerieException {
		TimeSerieObject<T> returnedTs = new TimeSerieObject<T>();
		DateMidnight theBDate = null;
		DateMidnight theEDate = null;

		if (bDate == null || bDate.isBefore(dates.get(0)))
			theBDate = dates.get(0);
		else
			theBDate = bDate;
		if (eDate == null)
			theEDate = dates.get(dates.size() - 1);
		else
			theEDate = eDate;

		for (int i = 0; i < dates.size(); i++) {
			if ((theBDate.equals(dates.get(i)) || theBDate.isBefore(dates.get(i)))
					&& (theEDate.equals(dates.get(i)) || theEDate.isAfter(dates.get(i)))) {
				returnedTs.add(dates.get(i), datas.get(i));
			}
		}
		return returnedTs;
	}

	/**
	 * Return all the dates
	 * @return
	 */
	public ArrayList<DateMidnight> getDates() {
		return dates;
	}

	/** 
	 * Return the specified value for the given date
	 * @param dt
	 * @return
	 */
	public T getValue(DateMidnight dt) {
		int idx = dates.indexOf(dt);
		return idx!=-1 ? datas.get(idx) : null;
	}

	/**
	 * Return value by idx
	 * @param idx
	 * @return
	 */
	public Object getValue(int idx) {
		return datas.get(idx);
	}

	/**
	 * Return all values contained in the timeserie
	 * @return
	 */
	public ArrayList<T> getValues() {
		return datas;
	}

	
	/**
	 * Returned the date for the idx
	 * @param idx
	 * @return
	 */
	public DateMidnight getDate(int idx) {
		return dates.get(idx);
	}
	
}
